在安裝好 mitmproxy 後,其實會得到三樣工具,分別是 : mitmproxy、mitmdump 和 mitmweb。
mitmproxy 和 mitmdump 都是 cli 界面的,差別在於 mitmproxy 有互動式界面,也可以看到完整的封包內容,mitmdump 則沒有。
mitmweb 就想像成是 mitmproxy 的 web 界面版本即可,執行後會額外在本地開啟網頁伺服器,讓你可以連上去看界面。
mitmproxy 有 --allow-hosts 和 --ignore-hosts 的參數可以用,通常比較常用的是 --allow-hosts。
如果客戶端有很多正在執行的程式,網路流量來自四面八方的時候,就可以用 --allow-hosts 去鎖定我們想撈封包的對象。
比方說某某手機 APP 專門和 example.com 互動,為了方便觀察,可以這樣下指令。
$ mitmproxy --allow-hosts example.com
這是 mitmproxy 強大的地方,可以讓你注入 Python script,有看過昨天的文章就能了解。
根據 mitmproxy 的 Python API 寫好的程式,可以使用 --scripts 或 -s 注入。
這是對封包進行更複雜操作的核心方法。
主要也是針對昨天的文章再做提醒。一旦劫持了連線,封包內容的一切都是可以被修改的。
不管是修改送出前的表單或 Headers,或者修改回傳後的回應。
如果客戶端想要去的是 A 網站,我們就讓他去 B 網站,這種事情當然也可以做到。
這種手法適合用於駭客想要讓客戶端去到我們自己寫的網站。
它和修改封包內容有點相似,反正內容都是自己準備好的,取決於你要不要多一個網頁伺服器 ?
我個人認為這和 shellcode 有異曲同工之妙。
如果說 shellcode 是自己寫 code,自己注入,自己執行,那麼中間人攻擊的重導向就是自己寫網站,自己綁架自己,自己執行。
既然需要一個網站,那麼就用 Flask 快速寫一個出來。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Yotsuba'
if __name__ == '__main__':
app.run()
同時需要寫一段 mitmproxy 的 script。
邏輯非常簡單,如果發現客戶端想去的網域是 example.com,無論協定是 HTTP 或 HTTPS 都強制改為 HTTP。
導向的網域是 localhost,5000 port 則是 Flask 預設的 port。
import mitmproxy
def request(flow: mitmproxy.http.HTTPFlow):
if flow.request.host == 'example.com':
flow.request.scheme = 'http'
flow.request.host = 'localhost'
flow.request.port = '5000'
不要忘記把 Flask 執行起來。
$ python3 your_flask_app.py
mitmproxy 在執行的時候,因為 Flask 那邊沒有 HTTPS,需要加上 --no-http2 參數。
我個人習慣,只有觀察封包的時候使用 mitmproxy。
在玩 mitmproxy 的 Python API 的時候就使用 mitmdump 去執行。
$ mitmdump --no-http2 -s your_script.py
測試一下,結果理所當然的是 Yotsuba。
$ curl --proxy "localhost:8080" "https://example.com"
這邊就不寫任何 if 判斷式了,任何流量一律不許通過。
import mitmproxy
def request(flow: mitmproxy.http.HTTPFlow):
mitmproxy.ctx.master.shutdown()
結果會是 curl: (52) Empty reply from server
$ curl --proxy "localhost:8080" "https://example.com"
以前在上汽車駕訓班的時候,考前需要複習筆試,所以就隨手下載一個評價高的題庫 APP。
由於 APP 有廣告,當時我就是讓手機連回電腦的網路,並且讓手機通過 mitmproxy,然後把跟廣告有關的網路封包都 shutdown 掉。